<template>
    <div class="shopcart">
        <div class="content" @click="toggleList">
            <div class="content-left">
                <!-- 购物车logo -->
                <div class="logo-wrapper" :class="hasBounce">
                    <div class="logo" :class="{'highlight':totalCount>0}">
                        <i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
                    </div>
                    <!-- 购物车logo上的已选商品数量 -->
                    <div class="num" v-show="totalCount>0">
                        <bubble :num="totalCount"></bubble>
                    </div>
                </div>
                <!-- 已选商品价格 -->
                <div class="price" :class="{'highlight':totalPrice>0}">￥{{totalPrice}}</div>
                <!-- 配送费 -->
                <div class="desc">另需配送费￥{{deliveryPrice}}元</div>
            </div>
            <!--  支付按钮   -->
            <div class="content-right">
                <div class="pay" @click="pay" :class="payClass">{{payDesc}}</div>
            </div>
        </div>
        <!--   动画小球 使用css设置动画时长与运动曲线 使用js计算小球初始位置   -->
        <div class="ball-container">
            <div v-for="(ball ,index) in balls" :key="index">
                <!-- 动画小球js钩子 -->
                <transition
                    @before-enter="beforeDrop"
                    @enter="dropping"
                    @after-enter="afterDrop">
                    <div class="ball" v-show="ball.show">
                        <div class="inner inner-hook"></div>
                    </div>
                </transition>
            </div>
        </div>
    </div>
</template>

<script>
    import Bubble from 'components/bubble/bubble'
    // 显示事件
    const EVENT_SHOW = 'show'
    // 隐藏事件
    const EVENT_HIDE = 'hide'
    // 添加按钮弹出小球的数量
    const BALL_LEN = 10
    // 左边距到购物车logo中心的位置
    const CART_LEFT = 32
    // 下边距到购物车logo中心的位置
    const CART_BOTTOM = 22
    // 构子
    const innerClsHook = 'inner-hook'

    /* 初始化小球 */
    function createBalls() {
        let ret = []
        for (let i = 0; i < BALL_LEN; i++) {
            ret.push({
                show: false
            })
        }
        return ret
    }

    export default {
        name: 'shop-cart',
        props: {
            /* 已选择商品 */
            selectFoods: {
                type: Array,
                default() {
                    return []
                }
            },
            /* 配送费 */
            deliveryPrice: {
                type: Number,
                default: 0
            },
            /* 最小起送价 */
            minPrice: {
                type: Number,
                default: 0
            },
            /* 购物车列表是否隐藏 */
            fold: {
                type: Boolean,
                default: true
            },
            /* 购物车列表事件来源 */
            isSticky: {
                type: Boolean,
                default: false
            },
            isGoods: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                // 购物车小球
                balls: createBalls(),
                // 已选商品列表
                listFold: this.fold,
                // 控制购物车logo弹跳动画的类 -> bounce
                hasBounce: ''
            }
        },
        computed: {
            /* 延迟计算的商品总价 */
            totalPrice() {
                let total = 0
                this.selectFoods.forEach((food) => {
                    total += food.price * food.count
                })
                return total
            },
            /* 立即计算的商品总价 */
            totalPriceImmediately() {
                let totalImmediately = 0
                this.selectFoods.forEach((food) => {
                    totalImmediately += food.price * food.countImmediately
                })
                return totalImmediately
            },
            /* 延迟计算的选择商品数量 */
            totalCount() {
                let count = 0
                this.selectFoods.forEach((food) => {
                    count += food.count
                })
                return count
            },
            /* 支付按钮描述 */
            payDesc() {
                if (this.totalPrice === 0) {
                    return `￥${this.minPrice}元起送`
                } else if (this.totalPrice < this.minPrice) {
                    let diff = this.minPrice - this.totalPrice
                    return `还差￥${diff}元起送`
                } else {
                    return '去结算'
                }
            },
            /* 是否达到支付条件 用于添加相应的class */
            payClass() {
                if (!this.totalCount || this.totalPrice < this.minPrice) {
                    return 'not-enough'
                } else {
                    return 'enough'
                }
            }
        },
        created() {
            // 正在下载小球数组
            // dropBalls不需要响应式 故不必放入data
            this.dropBalls = []
        },
        methods: {
            // 跳出小球
            drop(el) {
                for (let i = 0, len = this.balls.length; i < len; i++) {
                    const ball = this.balls[i]
                    if (!ball.show) {
                        ball.show = true
                        ball.el = el
                        // 存放入正在下载小球数组
                        this.dropBalls.push(ball)
                        return
                    }
                }
            },
            // 跳出小球前参数设置
            beforeDrop(el) {
                const ball = this.dropBalls[this.dropBalls.length - 1]
                // getBoundingClientRect用于获取某个元素相对于视窗的位置集合
                const rect = ball.el.getBoundingClientRect()
                // 计算小球从添加按钮到购物车中心所需的偏移量
                const x = rect.left - CART_LEFT
                const y = -(window.innerHeight - rect.top - CART_BOTTOM)

                // 显示小球
                el.style.display = ''
                // 设置纵轴轴初始位置
                el.style.transfrom = el.style.webkitTransform =
                    `translate3d(0, ${y}px, 0)`
                // 获得内部的元素
                const inner = el.getElementsByClassName(innerClsHook)[0]
                // 设置横轴初始位置
                inner.style.transfrom = inner.style.webkitTransform =
                    `translate3d(${x}px, 0, 0)`
            },
            // 小球跳出后的重绘
            dropping(el, done) {
                // 触发浏览器重绘
                this._reflow = document.body.offsetHeight
                // 设置纵轴目标位置
                el.style.transfrom = el.style.webkitTransform =
                    'translate3d(0, 0, 0)'
                // 获得内部的元素
                const inner = el.getElementsByClassName(innerClsHook)[0]
                // 设置横轴目标位置
                inner.style.transfrom = inner.style.webkitTransform =
                    'translate3d(0, 0, 0)'

                el.addEventListener('transitionend', done)
            },
            // 回收小球
            afterDrop(el) {
                const ball = this.dropBalls.shift()
                if (ball) {
                    // 回收小球
                    ball.show = false
                    el.style.display = 'none'
                    // 在小球过渡结束后 发起购物车logo弹跳动画
                    this.cartBounce()
                }
            },
            // 购物车弹跳动画
            cartBounce() {
                let _this = this
                if (this.hasBounce) {
                    return
                }
                this.hasBounce = 'bounce'
                // 手动移除类
                setTimeout(() => {
                    _this.hasBounce = ''
                }, 500)
            },
            // 支付事件 使用的是立即的count
            pay(event) {
                if (this.totalPrice < this.minPrice) {
                    return
                }
                // 提示框
                // 不进行缓存，防止其复用其他弹窗
                this.$createDialog({
                    title: '支付',
                    content: `您共需支付￥${this.totalPriceImmediately} 元`
                }).show()
                // 终止事件在传播过程的捕获、目标处理或冒泡阶段进一步传播。
                event.stopPropagation()
            },
            // 显示、隐藏购物车列表
            toggleList() {
                // 判断购物车列表是否隐藏
                if (this.listFold) {
                    if (!this.totalCount) {
                        return
                    }
                    this.listFold = false
                    // 显示购物车列表
                    this._showShopCartList()
                    // 触发事件隐藏已有购物车镜像，防止在food页面下显示购物车列表时
                    // 同时出现两个购物车镜像：food、购物车列表
                    this.$emit(EVENT_HIDE)
                    // 显示购物车的拷贝以覆盖于购物车列表之上
                    this._showShopCartSticky()
                } else {
                    this.listFold = true
                    this._hideShopCartList()
                }
            },
            // 显示购物车列表组件
            _showShopCartList() {
                this.shopCartListComp = this.shopCartListComp ||
                    this.$createShopCartList({
                        $props: {
                            selectFoods: 'selectFoods'
                        },
                        $events: {
                            hide: () => {
                                this.listFold = true
                            },
                            // 购物车列表组件在动画结束后触发的事件
                            leave: () => {
                                // 在food组件下显示购物车列表，
                                // 会先隐藏food中的购物车镜像
                                // 在列表移除时，需要触发事件 让food中的购物车显示
                                if (this.isGoods) {
                                    this.$emit(EVENT_SHOW)
                                }
                                this._hideShopCartSticky()
                            },
                            add: (el) => {
                                this.shopCartStickyComp.drop(el)
                            }
                        }
                    })
                this.shopCartListComp.show()
            },
            // 隐藏购物车列表组件
            _hideShopCartList() {
                // 判断隐藏事件来源 如果是sticky则调用购物车传给sticky的list中的hide
                const comp = this.isSticky ? this.$parent.list : this.shopCartListComp
                comp.hide && comp.hide()
            },
            // 显示购物车组件的镜像
            _showShopCartSticky() {
                this.shopCartStickyComp = this.shopCartStickyComp ||
                    this.$createShopCartSticky({
                        $props: {
                            selectFoods: 'selectFoods',
                            deliveryPrice: 'deliveryPrice',
                            minPrice: 'minPrice',
                            fold: 'listFold',
                            // 购物车列表组件
                            list: this.shopCartListComp
                        }
                    })
                this.shopCartStickyComp.show()
            },
            // 隐藏购物车镜像
            _hideShopCartSticky() {
                this.shopCartStickyComp.hide()
            }
        },
        watch: {
            fold(newVal) {
                this.listFold = newVal
            },
            totalCount(newVal) {
                if (!this.listFold && !newVal) {
                    this._hideShopCartList()
                }
            }
        },
        components: {
            Bubble
        }
    }
</script>

<style lang="stylus" scoped>
    @import "~common/stylus/mixin"
    @import "~common/stylus/variable"

    .shopcart
        height: 100%
        .content
            display   : flex
            background: $color-background
            font-size : 0
            color     : $color-light-grey
            .content-left
                flex: 1
                // 购物小车
                .logo-wrapper
                    display       : inline-block
                    vertical-align: top
                    position      : relative
                    top           : -10px
                    margin        : 0 12px
                    padding       : 6px
                    width         : 56px
                    height        : 56px
                    box-sizing    : border-box
                    border-radius : 50%
                    background    : $color-background
                    // 购物车logo弹跳动画
                    &.bounce
                        animation: bounce-y .5s
                    // 大小跳动
                    @keyframes bounce-in
                        0%
                            transform: scale(1)
                        20%
                            transform: scale(0.92)
                        40%
                            transform: scale(1.08)
                        60%
                            transform: scale(0.96)
                        80%
                            transform: scale(1.02)
                        100%
                            transform: scale(1)
                    // 上下跳动
                    @keyframes bounce-y
                        0%
                            transform: translateY(0)
                        20%
                            transform: translateY(10%)
                        40%
                            transform: translateY(-8%)
                        60%
                            transform: translateY(5%)
                        80%
                            transform: translateY(-2%)
                        100%
                            transform: translateY(0)
                    .logo
                        width        : 100%
                        height       : 100%
                        border-radius: 50%
                        text-align   : center
                        background   : $color-dark-grey
                        // 激活状态
                        &.highlight
                            background: $color-blue
                        .icon-shopping_cart
                            line-height: 44px
                            font-size: $fontsize-large-xxx
                            color: $color-light-grey
                            // 激活状态
                            &.highlight
                                color: $color-white
                    // 购物车logo上已选商品数量
                    .num
                        position : absolute
                        top      : 0
                        right    : 0
                // 选中商品总价
                .price
                    display       : inline-block
                    vertical-align: top
                    margin-top    : 12px
                    line-height   : 24px
                    padding-right : 12px
                    box-sizing    : border-box
                    border-right  : 1px solid rgba(255, 255, 255, 0.1)
                    font-weight   : 700
                    font-size     : $fontsize-large
                    // 激活状态
                    &.highlight
                        color: $color-white
                // 支付描述
                .desc
                    display: inline-block
                    vertical-align: top
                    margin: 12px 0 0 12px
                    line-height: 24px
                    font-size: $fontsize-small-s
            // 支付按钮
            .content-right
                flex: 0 0 105px
                width: 105px
                .pay
                    height: 48px
                    line-height: 48px
                    text-align: center
                    font-weight: 700
                    font-size: $fontsize-small
                    &.not-enough
                        background: $color-dark-grey
                    &.enough
                        background: $color-green
                        color: $color-white
        // 小球
        .ball-container
            .ball
                position: fixed
                left: 32px
                bottom: 22px
                z-index: 200
                transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
                .inner
                    width: 16px
                    height: 16px
                    border-radius: 50%
                    background: $color-blue
                    transition: all 0.4s linear
</style>
